<?php
/**
 * lsys task
 * @author     Lonely <shan.liu@msn.com>
 * @copyright  (c) 2017 Lonely <shan.liu@msn.com>
 * @license    http://www.apache.org/licenses/LICENSE-2.0
 */
namespace LSYS\Cron;
use \Redis;
class ExeJob{
	// 限制日志长度
	public static $redis_job_log_limit=100;
	// 日志记录KEY
	public static $redis_job_log="ltask_log";
	// 任务KEY
	public static $redis_job_exec="ltask_exec";
	private static $share_redis;
	public static function set_redis(\Redis $redis){
		self::$share_redis=$redis;
	}
	private static $exejob;
	public static function instance(){
		if (self::$exejob===null){
			if (self::$share_redis==null) throw new Exception("plase first set redis object.");
			self::$exejob= new self();
		}
		return self::$exejob;
	}
	
	private $redis;
	/**
	 * 任务执行类
	 */
	private function __construct(){
		$this->redis=self::$share_redis;
		$this->redis->setOption(\Redis::OPT_READ_TIMEOUT, -1);
	}
	/**
	 * 派发执行任务
	 * @param Job $job
	 */
	public function exec(Job $job){
		$this->redis->lPush(static::$redis_job_exec,$job->get_runer_string());
	}
	protected $_job;
	/**
	 * 任务进行监听
	 */
	public function listen(){
		$run=true;
		if (defined('LSYS_CRON_RUNER_FORK')&&LSYS_CRON_RUNER_FORK){
			if (!defined('LSYS_CRON_RUNER_LIMIT')) $run=1;
			else{
				if(LSYS_CRON_RUNER_LIMIT===true) $run=true;
				else $run=LSYS_CRON_RUNER_LIMIT>0?LSYS_CRON_RUNER_LIMIT:1;
			}
		}
		register_shutdown_function(array($this,'shutdown_function'));
		while ($run===true||$run-->0){
			@list($name,$this->_job)=$this->redis->brPop(static::$redis_job_exec,0);
			unset($name);
			if($this->_job==null) continue;
			$job=@unserialize($this->_job);
			if (!($job instanceof Runer)){
				$this->_add_log(array($this->_job,$e->getMessage()));
				unset($job);
				continue;
			}
			try{
				ob_start();
				$job->run();
				$data=ob_get_contents();
				ob_end_clean();
				$this->_add_log(array($this->_job,$data));
			}catch(\Exception $e){
				$this->_add_log(array($this->_job,$e->getMessage()));
			}
			unset($job,$data);
		}
	}
	public function shutdown_function(){
		if(ob_get_level()<=0) return ;
		$data=ob_get_contents();
		ob_end_clean();
		if (empty($this->_job))return ;
		$this->_add_log(array($this->_job,$data));
	}
	//记录运行日志
	protected function  _add_log(array $data){
		array_unshift($data,date("Y-m-d H:i:s"));
		$this->redis->lPush(static::$redis_job_log,json_encode($data));
		if(static::$redis_job_log_limit>0){
			$this->redis->LTRIM(static::$redis_job_log,0,static::$redis_job_log_limit);
		}
	}
}

